Skip to content

Add async support to SftpClient and SftpFileStream - #819

Merged
drieseng merged 11 commits into
sshnet:developfrom
IgorMilavec:TAP
Dec 14, 2021
Merged

Add async support to SftpClient and SftpFileStream#819
drieseng merged 11 commits into
sshnet:developfrom
IgorMilavec:TAP

Conversation

@IgorMilavec

@IgorMilavec IgorMilavec commented May 4, 2021

Copy link
Copy Markdown
Collaborator

Core async support requested by #153.

Added async support to BaseClient: (update 2021-05-11)

  • ConnectAsync

Added async support to SftpClient:

  • ListDirectoryAsync
  • GetStatusAsync
  • OpenAsync
  • DeleteFileAsync
  • RenameFileAsync
  • DownloadFileAsync
  • UploadFileAsync

Added async support to SftpFileStream:

  • OpenAsync
  • ReadAsync
  • WriteAsync
  • FlushAsync

Added net46 target to use async in .NET Framework.

This PR is intended to resolve #153.
This PR is intended to supersede #300 and #661.

Comment thread src/Renci.SshNet/Renci.SshNet.csproj Outdated
Comment thread src/Renci.SshNet/Sftp/SftpFileStream.cs
Comment thread src/Renci.SshNet/Sftp/SftpFileStream.cs
Comment thread src/Renci.SshNet/Sftp/SftpFileStream.cs
Comment thread src/Renci.SshNet/Sftp/SftpFileStream.cs Outdated
Comment thread src/Renci.SshNet/Sftp/SftpFileStream.cs Outdated
{
throw;
}
catch (Exception)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the generic class Exception be caught here? Or something more specific?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly, but I only reused the logic of sync versions of the functions at this time. When/if this is released, practice will show if any changes need to be made.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When FileMode is Create, I think we should just use Flags.CreateNewOrOpen | Flags.Truncate.
Let me run some checks later.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can confirm that it's ok to just add Flags.CreateNewOrOpen | Flags.Truncate when mode is FileMode.Create.

Comment thread src/Renci.SshNet/Sftp/SftpFileStream.cs
if (count < 0)
throw new ArgumentOutOfRangeException("count");
if ((buffer.Length - offset) < count)
throw new ArgumentException("Invalid array range.");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specify second parameter to ArgumentException, nameof(buffer).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about that, any of the three could be wrong, depending on the caller's intention. Anyhow, this is the same as the sync version, so we either need to change both or none...

/// <exception cref="SftpPermissionDeniedException">Permission to list the contents of the directory was denied by the remote host. <para>-or-</para> A SSH command was denied by the server.</exception>
/// <exception cref="SshException">A SSH error where <see cref="Exception.Message" /> is the message from the remote host.</exception>
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
public async Task<IEnumerable<SftpFile>> ListDirectoryAsync(string path, CancellationToken cancellationToken)

@vanillajonathan vanillajonathan May 11, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider returning ICollection or IReadOnlyCollection rather than IEnumerable as per the Microsoft Guidelines for Collections.

DO use Collection or a subclass of Collection for properties or return values representing read/write collections.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be IAsyncEnumerable<SftpFile>. It's only supported on .NET 4.6.1 or higher.
For .NET 4.6.1 and .NET Standard 2.0, you need to add a reference to Microsoft.Bcl.AsyncInterfaces.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then we need to remove FEATURE_TAP from netstandard1.3. Also, we take two "external" dependencies (AsyncInterfaces and Task.Extensions).
What if we leave this one as it is and add IAsyncEnumerable<SftpFile> EnumerateDirectoryAsync(...) for netstandard2.1+ ?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I won't let this block this merge request, but I still strongly consider changing this method to return IAsyncEnumerable<SftpFile>. I also don't like bringing in additional dependencies, but the alternative is not better.

Comment thread src/Renci.SshNet/Abstractions/DnsAbstraction.cs
@schaveyt

Copy link
Copy Markdown
Contributor

Any chance this could also target .net5 or .net6 as well

@IgorMilavec

Copy link
Copy Markdown
Collaborator Author

The library already targets netstandard2.0, so you can reference it from net5 or net6 projects.
It would only be beneficial for the library to target net5+ if it would use any net5+ features, like Spans etc. But this is out of scope of this issue and this PR. IMO we should remove legacy targets (please see #665) before adding any modern code.

@schaveyt

Copy link
Copy Markdown
Contributor

I did not connect those dots. Thank you for clarifying 👍

@paulmaybee

Copy link
Copy Markdown

This addition looks like it has a great deal of value. Is there a timetable or estimate for when the PR will be completed?

@IgorMilavec

Copy link
Copy Markdown
Collaborator Author

This PR if functionally complete IMO. It should also be stable, I have been running it in production since July. Now we need @drieseng to review and merge it.

@drieseng

Copy link
Copy Markdown
Member

@IgorMilavec Thanks, I'll try to find time in the coming days.

@IgorMilavec

Copy link
Copy Markdown
Collaborator Author

Figured this is the last chance to modify UploadFileAsync signature before this becomes a breaking change... :)

Comment thread src/Renci.SshNet/SftpClient.cs Outdated
Comment thread src/Renci.SshNet/Sftp/SftpSession.cs
This was referenced Aug 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for a Task based async API